package service

import (
	"context"
	"errors"
	bcrypt "golang.org/x/crypto/bcrypt"
	"hh/practice/internal/domain"
	"hh/practice/internal/repository"
)

var (
	ErrUserDuplicateEmail  = repository.ErrUserDuplicateEmail
	ErrUserNotFound        = repository.ErrUserNotFound
	ErrUserProfileNotFound = repository.ErrUserProfileNotFound

	ErrPasswordWrong     = errors.New("password wrong")
	ErrUserNameDuplicate = errors.New("此昵称已被使用")
)

type UserService struct {
	repo *repository.UserRepository
}

func NewUserService(repo *repository.UserRepository) *UserService {
	return &UserService{
		repo: repo,
	}
}

func (svc *UserService) Signup(c context.Context, u domain.User) error {
	p, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	u.Password = string(p)
	return svc.repo.Create(c, u)
}

func (svc *UserService) Login(c context.Context, email string, password string) (domain.User, error) {
	user, err := svc.repo.FindeByEmail(c, email)
	if err != nil {
		if err == ErrUserNotFound {
			return domain.User{}, ErrUserNotFound
		}
		return domain.User{}, err
	}
	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
	if err != nil {
		return user, ErrPasswordWrong
	}
	return user, nil
}

func (svc *UserService) Edit(c context.Context, profile domain.UserProfile) error {
	// 查uid是否存在，存在更新,否侧新建
	up, err := svc.repo.FindProfileByUid(c, profile.Uid)
	if err == ErrUserProfileNotFound {
		// 记录不存在，查昵称
		err := svc.isNameExist(c, profile)
		if err != nil {
			return err
		}
		//新建
		return svc.repo.CreateUserProfile(c, profile)
	}
	if err != nil {
		return err
	}
	// 记录存在， 查昵称是否重复
	if up.Name != profile.Name {
		err := svc.isNameExist(c, profile)
		if err != nil {
			return err
		}
	}
	profile.Id = up.Id
	return svc.repo.UpdateUserProfile(c, profile)
}

func (svc *UserService) isNameExist(c context.Context, profile domain.UserProfile) error {
	_, err := svc.repo.FindProfileByName(c, profile.Name)
	if err == nil {
		return ErrUserNameDuplicate
	}
	if err == ErrUserProfileNotFound {
		return nil
	}
	return err
}

func (svc *UserService) Profile(c context.Context, uid int64) (domain.UserProfile, error) {
	return svc.repo.FindProfileByUid(c, uid)
}
